import random
from enum import Enum


# TODO 注意：本utils中的部分代码最终应该拆分出来，再采用编译等手段，让它对layer的编写者是不可见的。如：get_peer_alive_has_disguised_access_ids

class GlobalVar:
    '''全局变量的定义'''
    network_status_red = None  # 红方的网络通信状况
    network_status_blue = None  # 蓝方的网络通信状况
    ops_status_red = None  # 红方所有算子当前信息状况
    ops_status_blue = None  # 蓝方所有算子当前信息状况
    current_actions = None  # 当前还未完成的列表(包括红蓝双方的)
    current_computing_resources_red = None  # 当前红方的算子资源
    current_computing_resources_blue = None  # 当前蓝方的算子资源
    current_attack_num = None  # 红蓝双方本轮发起的攻击数
    current_attack_success_num = None  # 红蓝双方本轮攻击成功次数
    communication_quality = None  # 红蓝双方通信质量
    last_step_communication_stop = None  # 红蓝双方上一轮是否有通信中断的算子


def get_network_status(color):
    '''
    获取网络通信状况
    '''
    if color == 0:  # 0代表红方，1代表蓝方
        return GlobalVar.network_status_red
    elif color == 1:
        return GlobalVar.network_status_blue


def set_network_status(color, value):
    '''
    设置网络通信状况
    '''
    if color == 0:
        GlobalVar.network_status_red = value
    elif color == 1:
        GlobalVar.network_status_blue = value


def get_last_step_communication_stop():
    '''
    获取红蓝双方上一轮是否有通信中断的算子
    '''
    return GlobalVar.last_step_communication_stop


def set_last_step_communication_stop(value):
    '''
    设置红蓝双方上一轮是否有通信中断的算子
    '''
    GlobalVar.last_step_communication_stop = value


def get_current_attack_num():
    '''
    获取红蓝双方本轮发起的攻击数
    '''
    return GlobalVar.current_attack_num


def set_current_attack_num(value):
    '''
    设置红蓝双方本轮发起的攻击数
    '''
    GlobalVar.current_attack_num = value


def get_current_attack_success_num():
    '''
    获取红蓝双方本轮攻击成功次数
    '''
    return GlobalVar.current_attack_success_num


def set_current_attack_success_num(value):
    '''
    设置红蓝双方本轮攻击成功次数
    '''
    GlobalVar.current_attack_success_num = value


def get_communication_quality():
    '''
    获取红蓝双方通信质量
    '''
    return GlobalVar.communication_quality


def set_communication_quality(value):
    '''
    设置红蓝双方通信质量
    '''
    GlobalVar.communication_quality = value


def get_ops_status(color):
    '''
    获取所有算子当前信息状况
    '''
    if color == 0:  # 0代表红方，1代表蓝方
        return GlobalVar.ops_status_red
    elif color == 1:
        return GlobalVar.ops_status_blue


def set_ops_status(color, value):
    '''
    设置所有算子当前信息状况
    '''
    if color == 0:
        GlobalVar.ops_status_red = value
    elif color == 1:
        GlobalVar.ops_status_blue = value


def get_current_computing_resources(color):
    '''
    获取算力资源
    '''
    if color == 0:  # 0代表红方，1代表蓝方
        return GlobalVar.current_computing_resources_red
    elif color == 1:
        return GlobalVar.current_computing_resources_blue


def set_current_computing_resources(color, value):
    '''
    设置算力资源
    '''
    if color == 0:
        GlobalVar.current_computing_resources_red = value
    elif color == 1:
        GlobalVar.current_computing_resources_blue = value


def get_current_actions():
    '''
    获取当前正在执行的任务列表
    '''
    return GlobalVar.current_actions


def set_current_actions(value):
    '''
    设置当前正在执行的任务列表
    '''
    GlobalVar.current_actions = value


def action_valid(action):
    '''
    检查该动作在本step是否可执行
    '''
    # 1、检查动作列表中是否已存在该动作，若已存在则不可合法
    type = action["type"]
    color = action["color"]
    current_actions = get_current_actions()
    if not current_actions is None:
        for item in current_actions:
            if color == item["color"] and type == item["type"]:
                return False
    # 2、检查目标算子的是否满足该攻击的前置条件，不满足则不合法
    if type == 103:  # 动作执行条件：我方与该算子之间通信中断
        if get_network_status(color)[action["ops_id"]] == False:
            return False
    elif type in (301, 302, 402):  # 动作执行条件：对方算子已被我方伪装接入
        ops_id = action["ops_id"]
        if get_ops_status(1 - color)[ops_id]["has_disguised_access"] == False:
            return False
    elif type == 403:  # 动作执行条件：对方算子密钥已被我方破解
        ops_id = action["ops_id"]
        if get_ops_status(1 - color)[ops_id]["has_cracked_key"] == False:
            return False
    # 3、检查算力资源是否允许执行该动作
    if get_current_computing_resources(color) < ACTION_COST_TIME[type]:
        return False
    else:  # 如果允许的话就将该方的算力资源做相应的扣除
        set_current_computing_resources(color, get_current_computing_resources(color) - ACTION_COST_TIME[type])
    return True


def get_info_action_name(id):
    """
    通过信息战动作的id得到对应的动作名称
    """
    action_names = {
        101: '无线通信',
        102: '人工通报',
        103: '网络重建',
        104: '通信信道切换',
        201: '网络入侵扫描',
        202: '病毒查杀',
        203: '网络流量检测',
        204: '密钥恢复',
        205: '认证强度提升',
        301: '暴力密钥破解',
        302: '后门密钥破解',
        303: '瘫痪攻击',
        304: '无线信号干扰',
        401: '伪装接入',
        402: '病毒植入',
        403: '信息窃取',
        404: '身份凭证伪造',
        501: '信息共享',
        502: '信息转发',
    }
    return action_names.get(id, '未知id')


def send_Msg_2_All(color, msg_body):
    """
    目的：用于庙算平台全局消息播报，用于展示消息战元素
    功能：返回发送全局消息的动作
    """
    return {
        "actor": 1 if color == 0 else 11,  # 此处为seat号，此处暂时先写死
        "type": 204,
        "to_all": 1,
        "msg_body": msg_body,
    }


def reset():
    '''
    重置所有全局变量的值
    '''
    GlobalVar.network_status_red = None
    GlobalVar.network_status_blue = None
    GlobalVar.ops_status_red = None
    GlobalVar.ops_status_blue = None
    GlobalVar.current_actions = None
    GlobalVar.current_computing_resources = None


# 信息战动作成功率裁决表
ACTION_SUCC_RATE = {
    101: 1,
    102: 1,
    103: 0.7,
    104: 0.8,
    201: 0.8,
    202: 0.8,
    203: 0.8,
    204: 0.5,
    205: 1,
    301: 0.4,
    302: 0.8,
    303: 0.6,
    304: 0.6,
    401: [0.2, 0.2],  # 由于伪装接入动作的成功率是动态变化的，所以此处使用列表存储成功率，两个值分别代表红方和蓝方的伪装接入动作成功率
    402: 0.6,
    403: 0.6,
    404: 0.5,
    501: 1,
    502: 1,
}

# 信息战动作耗费时间
ACTION_COST_TIME = {
    101: 1,
    102: 1,
    103: 10,
    104: 20,
    201: 60,
    202: 60,
    203: 60,
    204: 10,
    205: 40,
    301: 5,
    302: 20,
    303: 5,
    304: 20,
    401: 10,
    402: 10,
    403: 10,
    404: 15,
    501: 10,
    502: 10,
}


def get_peer_alive_ids(color):
    """
    获取未死亡的对方算子的id构成的列表
    说明：将这类方法抽取出来的原因：layer的编写者不能看到对面的信息，上帝视角只应该让裁决系统拥有。
    """
    alive_ids = []
    ops_status = get_ops_status(1 - color)
    for op_id, op_status in ops_status.items():
        if op_status["live_status"]:
            alive_ids.append(op_id)
    return alive_ids


def get_peer_alive_has_disguised_access_ids(color):
    """
    获取已成功伪装接入且未死亡的对方算子的id构成的列表
    说明：将这类方法抽取出来的原因：layer的编写者不能看到对面的信息，上帝视角只应该让裁决系统拥有。
    """
    has_disguised_access_ids = []
    ops_status = get_ops_status(1 - color)
    for op_id, op_status in ops_status.items():
        if (op_status["has_disguised_access"]) == True and op_status["live_status"] == True:
            has_disguised_access_ids.append(op_id)
    return has_disguised_access_ids


def reduce_packet_loss(network_status):
    """
    降低给定通信状况字典中的丢包率（幅度为0.05～0.30之间的随机值）
    """
    random_value = round(random.uniform(0.10, 0.30), 2)
    for key in network_status:
        # 生成0.10到0.30之间的随机值
        # 将原始值减去随机值，并确保结果在[0, 1]范围内
        modified_value = max(0, min(1, network_status[key] - random_value))
        # 更新字典中的值
        network_status[key] = modified_value
    return random_value


def increase_packet_loss(network_status):
    """
    增加给定通信状况字典中的丢包率（幅度为0.05～0.30之间的随机值）
    """
    random_value = round(random.uniform(0.10, 0.30), 2)
    for key in network_status:
        # 生成0.10到0.30之间的随机值
        # 将原始值加上随机值，并确保结果在[0, 1]范围内
        modified_value = max(0, min(1, network_status[key] + random_value))
        # 更新字典中的值
        network_status[key] = modified_value
    return random_value


def statistics_communication_quality():
    """
    统计通信质量百分比。
    算法：所有活着的算子的（1-丢包率）的平均值
    """
    res = {
        "red": 0.0,
        "blue": 0.0,
    }
    red_alive_ids = get_peer_alive_ids(1)
    count = len(red_alive_ids)
    total_sum = sum(1 - GlobalVar.network_status_red[op_id] for op_id in red_alive_ids)
    res["red"] = round(total_sum / count, 2) if count > 0 else 0
    blue_alive_ids = get_peer_alive_ids(0)
    count = len(blue_alive_ids)
    total_sum = sum(1 - GlobalVar.network_status_blue[op_id] for op_id in blue_alive_ids)
    res["blue"] = round(total_sum / count, 2) if count > 0 else 0
    # 将通信质量记录下来
    GlobalVar.communication_quality = res
    return res
